#include "rotation.h"
#include "settings/settings.h"
#include <cfloat>
#include <cmath>

Rotation::Rotation()
{
	maximum = DBL_MIN;
	connect(PointsGenerator::instance(),SIGNAL(onPointMap(double**, double)),this,SLOT(sPoints(double**, double)));
	int size = Settings::instance()->getSize();
	data1 = new unsigned char[size*size];
	preparedData = new unsigned char[size*size*3];
	sUpdateDegree();
	connect(Settings::instance(),SIGNAL(onUpdateDegree()),this,SLOT(sUpdateDegree()));
}

Rotation* Rotation::instance()
{
	static Rotation c;
	return &c;
}


void Rotation::sPoints(double** pkt, double maksimum)
{
	data = pkt;
	this->maximum=maksimum;
	makeRotation();
}


void Rotation::makeRotation()
{
	int size = Settings::instance()->getSize();
	int trans = size/2;
	for (int x=0; x <size; ++x)
		for (int y=0; y<size; ++y)
			data1[y*size+x] = 128;
	for (int x=0; x<size; ++x)
	{
		for (int y=0; y<size; ++y)
		{
			z = data[x][y];
			x1 = (x-trans)*cosB*cosC - (z-maximum/2)*sinB- (y-trans)*cosB*sinC+trans;
			y1 = (x-trans)*(cosA*sinC - cosC*sinA*sinB)+ (y-trans)*(cosA*cosC + sinA*sinB*sinC) - (z-maximum/2)*cosB*sinA+trans;
// 	      z1 = (x)*(sinA*sinC + cosA*cosC*sinB) + (y)*(cosC*sinA - cosA*sinB*sinC) + (z)*cosA*cosB+100;
			if (x1 > size || x1 < 0 || y1 > size || y1 < 0)
				continue;
				data1[(int)y1*size+(int)x1] =  (data[x][y]/maximum*127+128)/**(sinC>=0?1:-1)*/;
		}
	}

	#ifdef APROX_ON
	for (int x=1; x <size-1; ++x)
	{
		for (int y=1; y<size-1; ++y)
		{
			data1[y*size+x] =
			(
				data1[(y-1)*size+x]+
				data1[(y+1)*size+x]+
				data1[y*size+x+1]+
				data1[y*size+x-1]+
				data1[(y-1)*size+x-1]+
				data1[(y-1)*size+x+1]+
				data1[(y+1)*size+x-1]+
				data1[(y+1)*size+x+1]
			)/8;
		}
	}
	#endif

	for(int i=0;i<size*size*3;i+=3){
		preparedData[i] = data1[i/3];
		preparedData[i+1] = 100;
		preparedData[i+2] = 255-data1[i/3];
	}
	emit onPoints(preparedData);
}

void Rotation::sUpdateDegree()
{
	Aa=Settings::instance()->getKA();
	Ba=Settings::instance()->getKB();
	Ca=Settings::instance()->getKC();
	cosA = cos(Aa*M_PI/180);
	sinA = sin(Aa*M_PI/180);
	cosB = cos(Ba*M_PI/180);
	sinB = sin(Ba*M_PI/180);
	cosC = cos(Ca*M_PI/180);
	sinC = sin(Ca*M_PI/180);
}

